package com.creator.pangu.core.security.util;

import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JwtUtil:用来进行签名和效验Token
 *
 * @author zhangxiaoxiang
 * @date: 2019/07/12
 */
@Slf4j
@Component
public class JWTUtil {

    @Value("${token.auth-header}")
    private String authHeader;

    @Value("${token.auth-type}")
    private String authType;

    @Value("${token.expire-time}")
    private long expireTime;

    @Value("${token.secret}")
    private String secret;

    @Value("${token.claim-sub}")
    private String claimSub;


    /**
     * 校验token是否正确
     *
     * @param token    密钥
     * @param userName 用户的密码
     * @return 是否正确
     */
    public boolean verify(String token, String userName) {
        try {
            //根据秘钥生成JWT效验器
            Algorithm algorithm = Algorithm.HMAC512(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withClaim(claimSub, userName)
                    .build();
            //效验TOKEN
            DecodedJWT jwt = verifier.verify(token);
            log.info("登录验证成功!");
            return true;
        } catch (Exception exception) {
            log.error("JwtUtil登录验证失败!");
            return false;
        }
    }

    /**
     * 获得token中的信息无需secret解密也能获得
     *
     * @return token中包含的用户名
     */
    public String getUserNameByToken(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(claimSub).asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    /**
     * 请求头获得userName
     *
     * @param request
     * @return
     */
    public String getTokenByRequest(HttpServletRequest request) {
        String token = request.getHeader(authHeader);
        if (StrUtil.isNotEmpty(token) && token.startsWith(authType)) {
            token = token.substring(authType.length());
        }
        return token;
    }

    /**
     * 生成token签名EXPIRE_TIME 分钟后过期
     *
     * @param userName 用户登录名
     * @return 加密的token
     */
    public String sign(String userName) {
        Date date = new Date(System.currentTimeMillis() + expireTime * 60 * 1000);
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS512");
        map.put("typ", "JWT");
        Algorithm algorithm = Algorithm.HMAC512(secret);
        // 附带username信息
        return JWT.create()
                .withHeader(map)
                .withClaim(claimSub, userName)
                .withExpiresAt(date)
                .sign(algorithm);

    }

    /**
     * token是否过期
     *
     * @return true：过期
     */
    public static boolean isTokenExpired(String token) {
        Date now = Calendar.getInstance().getTime();
        DecodedJWT jwt = JWT.decode(token);
        return jwt.getExpiresAt().before(now);
    }

    public static void main(String[] args) {
        /**
         * 测试生成一个token
         */
//        String sign = new JWTUtil().sign("lijunjie");
//        log.info("测试生成一个token\n" + sign);


        Date date = new Date(System.currentTimeMillis() + 30 * 24 * 60 * 60 * 1000L);
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS512");
        map.put("typ", "JWT");
        Algorithm algorithm = Algorithm.HMAC512("pangu.open.the.sky.split.the.ground");
        // 附带username信息
        String token = JWT.create()
                .withHeader(map)
                .withClaim("sub", "lijunjie")
                .withExpiresAt(date)
                .sign(algorithm);
        log.info(token);

//        System.out.println(new JWTUtil().verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJsaWp1bmppZSIsImV4cCI6MTY4NTg1MDI1M30.OkTmeEXdLBTHFIMh98IX5-kG6CL7qIvaP88ayND2yUkD3MqjlwzlcuVM-pNqh4Z7H33U13gluW8BaMpKyc_DxA","lijunjie"));
//
//        log.info(getUserId("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzYyNDk5NTQsInVzZXJJZCI6ImxlZSJ9.xHXeaIwLlrn8xlyoVlmeA6GqKqZhZb3D8HwXE4G65UY"));

    }
}